package com.kly.springbootinit.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kly.springbootinit.annotation.AuthCheck;
import com.kly.springbootinit.common.BaseResponse;
import com.kly.springbootinit.common.ErrorCode;
import com.kly.springbootinit.common.ResultUtils;
import com.kly.springbootinit.common.UserContext;
import com.kly.springbootinit.constant.UserConstant;
import com.kly.springbootinit.exception.ThrowUtils;
import com.kly.springbootinit.model.dto.order.OrderAddRequest;
import com.kly.springbootinit.model.dto.order.OrderEditRequest;
import com.kly.springbootinit.model.dto.order.OrderQueryRequest;
import com.kly.springbootinit.model.entity.Orders;
import com.kly.springbootinit.model.entity.User;
import com.kly.springbootinit.model.entity.Vehicle;
import com.kly.springbootinit.model.enums.OrderStatusEnum;
import com.kly.springbootinit.model.enums.VehicleStatus;
import com.kly.springbootinit.model.vo.OrderVO;
import com.kly.springbootinit.model.vo.VehicleVO;
import com.kly.springbootinit.service.OrderService;
import com.kly.springbootinit.service.UserService;
import com.kly.springbootinit.service.VehicleService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author admin
 * @date 2025/5/22
 */
@RestController
@RequestMapping("/orders")
public class OrderController {

    @Resource
    private OrderService orderService;

    @Resource
    private VehicleService vehicleService;

    @Resource
    private UserService userService;


    /**
     * 创建租车订单
     */
    @PostMapping("/createOrder")
    public BaseResponse<OrderVO> createOrder(@RequestBody OrderAddRequest orderAddRequest) {
        ThrowUtils.throwIf(orderAddRequest == null, ErrorCode.PARAMS_ERROR);
        // 操作数据库
        return ResultUtils.success(orderService.createOrder(orderAddRequest));
    }

    /**
     * 获取订单列表
     */
    @GetMapping("/list/vo")
    public BaseResponse<Page<OrderVO>> listOrder(OrderQueryRequest orderQueryRequest) {
        // 操作数据库
        ThrowUtils.throwIf(orderQueryRequest == null, ErrorCode.PARAMS_ERROR);
        Long userId = orderQueryRequest.getUserId();
        Long vehicleId = orderQueryRequest.getVehicleId();
        Date startTime = orderQueryRequest.getStartTime();
        Date endTime = orderQueryRequest.getEndTime();
        BigDecimal totalCost = orderQueryRequest.getTotalCost();
        Integer status = orderQueryRequest.getStatus();
        int current = orderQueryRequest.getCurrent();
        int pageSize = orderQueryRequest.getPageSize();
        Page<Orders> page = orderService.lambdaQuery()
                .eq(userId != null, Orders::getUserId, userId)
                .eq(vehicleId != null, Orders::getVehicleId, vehicleId)
                .ge(startTime != null, Orders::getStartTime, startTime)
                .le(endTime != null, Orders::getEndTime, endTime)
                .eq(totalCost != null, Orders::getTotalCost, totalCost)
                .eq(status != null, Orders::getStatus, status)
                .orderByDesc(Orders::getCreateTime)
                .page(new Page<>(current, pageSize));

        // Page
        Page<OrderVO> pageVO = new Page<>(current, pageSize, page.getTotal());
        List<Orders> records = page.getRecords();
        if (CollUtil.isEmpty(records)) {
            return ResultUtils.success(pageVO);
        }
        List<OrderVO> orderVOList = BeanUtil.copyToList(records, OrderVO.class);
        //     获取userId vehicleId
        Set<Long> userIdSet = orderVOList.stream().map(OrderVO::getUserId).collect(Collectors.toSet());
        Set<Long> vehicleIdSet = orderVOList.stream().map(OrderVO::getVehicleId).collect(Collectors.toSet());
        //     获取map集合
        Map<Long, List<User>> userIdUserMap = userService.listByIds(userIdSet).stream().collect(Collectors.groupingBy(User::getId));
        Map<Long, List<Vehicle>> vehicleIdVehicleMap = vehicleService.listByIds(vehicleIdSet).stream().collect(Collectors.groupingBy(Vehicle::getId));

        List<OrderVO> orderVOS = orderVOList.stream().map(orderVO -> {
            Long userId1 = orderVO.getUserId();
            Long vehicleId1 = orderVO.getVehicleId();
            User user = null;
            Vehicle vehicle = null;
            if (userIdSet.contains(userId1)) {
                user = userIdUserMap.get(userId1).get(0);
            }
            if (vehicleIdSet.contains(vehicleId1)) {
                vehicle = vehicleIdVehicleMap.get(vehicleId1).get(0);
            }
            orderVO.setUserVO(userService.getUserVO(user));
            orderVO.setVehicleVO(BeanUtil.copyProperties(vehicle, VehicleVO.class));
            return orderVO;
        }).collect(Collectors.toList());
        pageVO.setRecords(orderVOS);
        return ResultUtils.success(pageVO);
    }

    /**
     * 获取订单列表 管理员
     */
    @GetMapping("/list/po")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<Orders>> listOrderPo(OrderQueryRequest orderQueryRequest) {
        ThrowUtils.throwIf(orderQueryRequest == null, ErrorCode.PARAMS_ERROR);
        Long userId = orderQueryRequest.getUserId();
        Long vehicleId = orderQueryRequest.getVehicleId();
        Date startTime = orderQueryRequest.getStartTime();
        Date endTime = orderQueryRequest.getEndTime();
        BigDecimal totalCost = orderQueryRequest.getTotalCost();
        Integer status = orderQueryRequest.getStatus();
        int current = orderQueryRequest.getCurrent();
        int pageSize = orderQueryRequest.getPageSize();
        Page<Orders> page = orderService.lambdaQuery()
                .eq(userId != null, Orders::getUserId, userId)
                .eq(vehicleId != null, Orders::getVehicleId, vehicleId)
                .ge(startTime != null, Orders::getStartTime, startTime)
                .le(endTime != null, Orders::getEndTime, endTime)
                .eq(totalCost != null, Orders::getTotalCost, totalCost)
                .eq(status != null, Orders::getStatus, status)
                .orderByDesc(Orders::getCreateTime)
                .page(new Page<>(current, pageSize));
        return ResultUtils.success(page);
    }

    /**
     * 通过订单id获取订单
     */
    @GetMapping
    public BaseResponse<OrderVO> getOrder(@RequestParam("id") Long id, HttpServletRequest request) {
        ThrowUtils.throwIf(id == null, ErrorCode.PARAMS_ERROR);
        Orders orders = orderService.getById(id);
        ThrowUtils.throwIf(orders == null, ErrorCode.PARAMS_ERROR);
        OrderVO orderVO = BeanUtil.copyProperties(orders, OrderVO.class);
        // 查询vehicle
        Vehicle vehicle = vehicleService.getById(orderVO.getVehicleId());
        VehicleVO vehicleVO = BeanUtil.copyProperties(vehicle, VehicleVO.class);
        orderVO.setVehicleVO(vehicleVO);
        // 获取用户信息
        User loginUser = userService.getLoginUser(request);
        orderVO.setUserVO(userService.getUserVO(loginUser));
        return ResultUtils.success(orderVO);
    }

    /**
     * 通过订单id删除订单
     */
    @DeleteMapping(("/{id}"))
    public BaseResponse<Boolean> deleteOrder(@PathVariable("id") Long id) {
        ThrowUtils.throwIf(id == null, ErrorCode.PARAMS_ERROR);
        boolean b = orderService.removeById(id);
        return ResultUtils.success(b);
    }

    /**
     * 使用车辆
     */
    @PutMapping(("/use/{id}"))
    public BaseResponse<Boolean> useOrder(@PathVariable("id") Long id) {
        ThrowUtils.throwIf(id == null, ErrorCode.PARAMS_ERROR);
        Orders ordersDb = orderService.getById(id);
        ThrowUtils.throwIf(ordersDb == null, ErrorCode.PARAMS_ERROR);
        boolean update = orderService.lambdaUpdate()
                .eq(Orders::getId, id)
                .eq(Orders::getStatus, OrderStatusEnum.PAID.getCode())
                .eq(Orders::getUserId, UserContext.getUser().getId())
                .set(Orders::getStatus, OrderStatusEnum.PROCESSING.getCode())
                .set(Orders::getStartTime, new Date())
                .update();
        ThrowUtils.throwIf(!update, ErrorCode.PARAMS_ERROR, "订单状态修改失败");
        return ResultUtils.success(true);
    }

    /**
     * 完成/取消租车订单
     */
    @PutMapping(("/finish/{id},{status}"))
    @Transactional(rollbackFor = RuntimeException.class)
    public BaseResponse<Boolean> finishOrder(@PathVariable("id") Long id, @PathVariable("status") Integer status) {
        ThrowUtils.throwIf(id == null, ErrorCode.PARAMS_ERROR);
        Orders ordersDb = orderService.getById(id);
        ThrowUtils.throwIf(ordersDb == null, ErrorCode.PARAMS_ERROR);
        orderService.lambdaUpdate()
                .eq(Orders::getId, id)
                .eq(Orders::getStatus, OrderStatusEnum.PROCESSING.getCode())
                .eq(Orders::getUserId, UserContext.getUser().getId())
                .set(Orders::getStatus, status)
                .set(Orders::getEndTime, new Date())
                .update();
        // 修改车辆状态
        boolean update = vehicleService.lambdaUpdate()
                .eq(Vehicle::getId, ordersDb.getVehicleId())
                .ne(Vehicle::getStatus, VehicleStatus.MAINTENANCE.getStatus())
                .set(Vehicle::getStatus, VehicleStatus.AVAILBLE.getStatus())
                .update();
        ThrowUtils.throwIf(!update, ErrorCode.PARAMS_ERROR, "车辆状态修改失败");
        return ResultUtils.success(true);
    }

    /**
     * 修改订单
     */
    @PutMapping
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> updateOrder(OrderEditRequest orderEditRequest) {
        ThrowUtils.throwIf(orderEditRequest == null, ErrorCode.PARAMS_ERROR);
        Orders orders = BeanUtil.copyProperties(orderEditRequest, Orders.class);
        boolean update = orderService.updateById(orders);
        ThrowUtils.throwIf(!update, ErrorCode.PARAMS_ERROR);
        return ResultUtils.success(true);
    }
}
